﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using StructureMap;

namespace MathematicallySafe.HeadCounter.Data.Models
{
    public enum LootOutcome
    {
        Won,
        Offspec,
        Banked,
        Disenchanted,
    }

    public class RaidLoot
    {
        private static Guild _guild;
        private static Guild Guild
        {
            get
            {
                if (_guild == null)
                {
                    _guild = ObjectFactory.GetInstance<IHeadCounterService>().Guild;
                }

                return _guild;
            }
        }
        
        private static LootTable _lootTable;
        private static LootTable LootTable
        {
            get
            {
                if (_lootTable == null)
                {
                    _lootTable = ObjectFactory.GetInstance<IHeadCounterService>().LootTable;
                }

                return _lootTable;
            }
        }

        private LootItem _item;
        private LootOutcome _outcome;
        private string _winner;

        [XmlAttribute]
        public int ID { get; set; }

        [XmlAttribute]
        public DateTime Time { get; set; }

        [XmlAttribute]
        public string Winner
        {
            get { return _winner; }
            set
            {
                if (_winner != value)
                {
                    string originalWinner = _winner;
                    _winner = value;

                    if (Outcome == LootOutcome.Won)
                    {
                        var raider = Guild.FindRaider(_winner);
                        if (raider != null)
                        {
                            if (_item != null) raider.AddGear(_item.ID, true);
                            WinnerIdentity = raider.Identity;
                        }
                    }
                    else
                    {
                        WinnerIdentity = null;
                    }

                    if (originalWinner != null)
                    {
                        var originalRaider = Guild.FindRaider(originalWinner);
                        if (originalRaider != null) originalRaider.RemoveGear(_item.ID);
                    }

                    OnWinnerChanged(new WinnerChangedEventArgs(originalWinner, _winner));
                }
            }
        }

        [XmlAttribute]
        public string WinnerIdentity { get; set; }

        [XmlAttribute]
        public string ItemName { get; set; }

        [XmlAttribute]
        public string Boss { get; set; }

        [XmlElement]
        public LootOutcome Outcome
        {
            get { return _outcome; }
            set
            {
                if (_outcome != value)
                {
                    var originalOutcome = _outcome;
                    _outcome = value;

                    OnOutcomeChanged(new OutcomeChangedEventArgs(originalOutcome, _outcome));

                    if (_outcome != LootOutcome.Won)
                    {
                        Winner = null;
                    }
                }
            }
        }

        [XmlIgnore]
        public LootItem Item
        {
            get
            {
                if (_item == null)
                {
                    _item = LootTable[ID];
                }

                return _item;
            }
        }

        public event EventHandler<WinnerChangedEventArgs> WinnerChanged;

        protected virtual void OnWinnerChanged(WinnerChangedEventArgs e)
        {
            if (WinnerChanged != null)
            {
                WinnerChanged(this, e);
            }
        }

        public event EventHandler<OutcomeChangedEventArgs> OutcomeChanged;

        protected virtual void OnOutcomeChanged(OutcomeChangedEventArgs e)
        {
            if (OutcomeChanged != null)
            {
                OutcomeChanged(this, e);
            }
        }
    }

    public class WinnerChangedEventArgs : EventArgs
    {
        public readonly string OriginalWinner;
        public readonly string NewWinner;

        public WinnerChangedEventArgs(string originalWinner, string newWinner)
        {
            OriginalWinner = originalWinner;
            NewWinner = newWinner;
        }
    }

    public class OutcomeChangedEventArgs : EventArgs
    {
        public readonly LootOutcome OriginalOutcome;
        public readonly LootOutcome ChangedOutcome;

        public OutcomeChangedEventArgs(LootOutcome originalOutcome, LootOutcome changedOutcome)
        {
            OriginalOutcome = originalOutcome;
            ChangedOutcome = changedOutcome;
        }
    }
}